/**
  **************************************************************************
  * @file     msc_diskio.c
  * @version  v2.1.0
  * @date     2022-06-09
  * @brief    usb mass storage disk function
  **************************************************************************
  *                       Copyright notice & Disclaimer
  *
  * The software Board Support Package (BSP) that is made available to
  * download from Artery official website is the copyrighted work of Artery.
  * Artery authorizes customers to use, copy, and distribute the BSP
  * software and its related documentation for the purpose of design and
  * development in conjunction with Artery microcontrollers. Use of the
  * software is governed by this copyright notice and the following disclaimer.
  *
  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
  *
  **************************************************************************
  */
#include "./usbd_class/msc/msc_diskio.h"
#include "./usbd_class/msc/msc_bot_scsi.h"
#include "./spim/spim.h"
#include "./spiflash/spiflash.h"
#include "./sdio/sdio_sdcard.h"


/* Definitions of physical drive number for each drive */
#define FLASH_SECTOR_SIZE   512
#define FLASH_FATFS_BASE    0			/* FATFS 在外部FLASH的起始地址 从0开始 */

/* 自己定义的一个标记USB状态的寄存器, 方便判断USB状态
 * bit0 : 表示电脑正在向SD卡写入数据
 * bit1 : 表示电脑正从SD卡读出数据
 * bit2 : SD卡写数据错误标志位
 * bit3 : SD卡读数据错误标志位
 * bit4 : 1,表示电脑有轮询操作(表明连接还保持着)
 */
volatile uint8_t g_usb_state_reg = 0;

uint32_t sector_size = 2048;
uint32_t msc_flash_size;

/** @addtogroup 403A_USB_device_msc
  * @{
  */

uint8_t scsi_inquiry[MSC_SUPPORT_MAX_LUN][SCSI_INQUIRY_DATA_LENGTH] =
{
  /* lun = 0 */
  {
    0x00,         /* peripheral device type (direct-access device) */
    0x80,         /* removable media bit */
    0x00,         /* ansi version, ecma version, iso version */
    0x01,         /* respond data format */
    SCSI_INQUIRY_DATA_LENGTH - 5, /* additional length */
    0x00, 0x00, 0x00, /* reserved */
    'S', 'P', 'I', 'F', 'L', 'A', 'S', 'H', /* vendor information "AT32" */
    'D', 'i', 's', 'k', '0', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', /* Product identification "Disk" */
    '2', '.', '0', '0'  /* product revision level */
  },
  /* lun = 1 */
  {
    0x00,         /* peripheral device type (direct-access device) */
    0x80,         /* removable media bit */
    0x00,         /* ansi version, ecma version, iso version */
    0x01,         /* respond data format */
    SCSI_INQUIRY_DATA_LENGTH - 5, /* additional length */
    0x00, 0x00, 0x00, /* reserved */
    'S', 'D', 'C', 'A', 'R', 'D', ' ', ' ', /* vendor information "AT32" */
    'D', 'i', 's', 'k', '1', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', /* Product identification "Disk" */
    '2', '.', '0', '0'  /* product revision level */
  }
};

/**
  * @brief  get disk inquiry
  * @param  lun: logical units number
  * @retval inquiry string
  */
uint8_t *get_inquiry(uint8_t lun)
{
  g_usb_state_reg |= 0X10;		/* 标记轮询 */
	
  if(lun < MSC_SUPPORT_MAX_LUN)
    return (uint8_t *)scsi_inquiry[lun];
  else
    return NULL;
}

/**
  * @brief  disk read
  * @param  lun: logical units number
  * @param  addr: logical address
  * @param  read_buf: pointer to read buffer
  * @param  len: read length
  * @retval status of usb_sts_type
  */
usb_sts_type msc_disk_read(uint8_t lun, uint32_t addr, uint8_t *read_buf, uint32_t len)
{
  int8_t res = 0;	
  g_usb_state_reg |= 0X02;		/* 标记正在读数据 */

  switch(lun)
  {
    case 0:
      flash_spi_read((uint8_t *)read_buf, (FLASH_FATFS_BASE + addr), len);
      break;
    case 1:
	  res = sd_read_disk((uint8_t *)read_buf, addr/FLASH_SECTOR_SIZE, len/FLASH_SECTOR_SIZE);
      break;
  }
  
  if (res) {
    printf("rerr:%d,%d\r\n", lun, res);
    g_usb_state_reg |= 0X08;	/* 读错误! */
  }
  
  return USB_OK;
}

/**
  * @brief  disk write
  * @param  lun: logical units number
  * @param  addr: logical address
  * @param  buf: pointer to write buffer
  * @param  len: write length
  * @retval status of usb_sts_type
  */
usb_sts_type msc_disk_write(uint8_t lun, uint32_t addr, uint8_t *buf, uint32_t len)
{
  int8_t res = 0;
  g_usb_state_reg |= 0X01;    /* 标记正在写数据 */
	
  switch(lun)
  {
    case 0:
	  flash_spi_write((uint8_t *)buf, (FLASH_FATFS_BASE + addr), len);
      break;
	case 1:
	  res = sd_write_disk((uint8_t *)buf, addr/FLASH_SECTOR_SIZE, len/FLASH_SECTOR_SIZE);
      break;
  }
  
  if (res) {
    g_usb_state_reg |= 0X04;    /* 写错误! */
    printf("werr:%d,%d\r\n", lun, res);
  }
  
  return USB_OK;
}

/**
  * @brief  disk capacity
  * @param  lun: logical units number
  * @param  blk_nbr: pointer to number of block
  * @param  blk_size: pointer to block size
  * @retval status of usb_sts_type
  */
usb_sts_type msc_disk_capacity(uint8_t lun, uint32_t *blk_nbr, uint32_t *blk_size)
{
  switch(lun)
  {
    case SPI_FLASH_LUN:
	  *blk_nbr = (4 * 1024 * 1024 + 896 * 1024) / FLASH_SECTOR_SIZE;
      *blk_size = FLASH_SECTOR_SIZE;
      break;
    case SD_LUN:
	  *blk_nbr = g_sd_card_info.CardCapacity / FLASH_SECTOR_SIZE;
      *blk_size = FLASH_SECTOR_SIZE;
      break;
    default:
      break;
  }
  return USB_OK;
}

/**
  * @}
  */

/**
  * @}
  */
